4. 数据类型与舍入 / NaN 口径(勘误 v0.1.2)
整数:二补码,窄结果截断。div/divu/rem/remu 按 RISC-V M 扩展结果(除零、INT_MIN / -1 回绕),永不陷阱——优先于 ISA.md §6 中"除零可产生陷阱"的一般表述。
4.1 MODE 位布局
| 位 | 字段 | 说明 |
|---|---|---|
| [2:0] | rm | binary32 舍入 |
| [5:3] | rm16 | binary16 舍入;7 = 动态(跟随 rm) |
| [8:6] | rm64 | binary64 舍入;7 = 动态(跟随 rm) |
| [9] / [10] | DAZ32 / FTZ32 | binary32 输入 / 输出冲零 |
| [11] / [12] | DAZ16 / FTZ16 | binary16 |
| [13] / [14] | DAZ64 / FTZ64 | binary64 |
| [20:16] | 陷阱使能 | 位序同 fflags |
| 其余 | 保留 | 必须为 0 |
复位值 MODE = 0(IEEE、RNE、保留次正规数、不陷入)。舍入编码 0..4 = RNE/RTZ/RDN/RUP/RMM。任一 rm 字段取 5/6、rm 取 7 或保留位非零:写入触发 IllegalMode(cause 8,trapinfo = 组合后的候选 MODE 值,MODE 不变);指令 rm 操作数取 5/6 触发 IllegalInsn(cause 1,trapinfo = 指令字)。
4.2 舍入模式选择
- 显式
rm操作数优先;dyn(7)或无 rm 操作数的指令按结果宽度选 MODE 字段(binary32 →rm、binary16 →rm16、binary64 →rm64;该字段为 7 时再读rm)。 - YAML 中
fcvt.f16.f32.lo/hi语义写的 "MODE.rm" 是笔误,按勘误应为MODE.rm16。 - 舍入不受 rm 影响的指令:
ffloor/fceil/ftrunc/frndne(方向固定,不置 NX)、fcvt.i32/u32.f32与fcvt.i16/u16.f16(固定 RTZ);.m变体用显式 rm;fmed3.f32、dot2.f32.f16用MODE.rm。
4.3 fflags
RISC-V 位序:[0] NX、[1] UF、[2] OF、[3] DZ、[4] NV。只累积 EXEC 内活跃 lane 产生的标志;写入只保留 [4:0](高位丢弃,不陷阱)。使能异常(MODE[20:16],位序同 fflags)触发 cause 4:该指令不写回、不排挂起操作,但保留本条新置起的 fflags。
4.4 DAZ / FTZ
- DAZ 把次正规输入冲成带符号 0,不置标志;FTZ 把舍入后的次正规结果冲成带符号 0,置 UF|NX(精确的次正规结果同样冲零;FTZ 关时按 RISC-V 规则:tiny 且不精确才置 UF)。
- 转换指令:DAZ 看源宽度、FTZ 看结果宽度(如
fcvt.f16.f32.*用 DAZ32 + FTZ16,dot2.f32.f16的 f16 源用 DAZ16、s3 用 DAZ32、结果 FTZ32)。 - min/max/med3/fsat 不做 FTZ(结果是某个输入本身,不经过舍入)。
- 符号注入(
fsgnj*)、neg/abs修饰、move 和fclass不受 DAZ/FTZ 影响;fsgnj*与cmp.class.*虽带fp_mode标志仍按此处理(标志规则优先)。 - 不带
fp_mode的指令不做 DAZ/FTZ:cmp.*.f64(标志与使能陷阱照常)、frexp.exp.f32;rcp/rsq.f64固定 RNE 且不做 DAZ/FTZ。
4.5 NaN 与比较
- 算术结果的 NaN 为规范 quiet NaN:f32
0x7FC00000、f160x7E00、f640x7FF8000000000000;sNaN 输入置 NV。 - 比较谓词:有序
lt/le/gt/ge为 signaling(任一操作数 NaN——含 qNaN——置 NV);eq/ne、o/u与无序equ/neu/ltu/leu/gtu/geu为 quiet(只有 sNaN 置 NV)。f16/f32/f64 一致。cmp.ne= "有序且不等"(任一 NaN → false),不是eq的取反;"无序或不等"是neu。 fmin/fmax(三种宽度)与浮点原子fmin/fmax:IEEE 754-2019 minimumNumber/maximumNumber——单 NaN 返回另一操作数、双 NaN 返回规范 NaN、-0 < +0。fmed3遇 NaN 返回非 NaN 值的 min3(AMD 风格),不按字面 fmin/fmax 组合。frexp.mant(三种宽度)对 NaN/inf 原样透传(保留 payload)、不置任何标志(sNaN 也不置 NV);frexp.exp对 0/inf/NaN 返回 0、从不置标志。- 取整类(floor/ceil/trunc/rndne)不置 NX(对应 RISC-V
fround);ffract结果钳到 < 1.0 的最大值(f320x3F7FFFFF、f160x3BFF),±inf 输入得规范 NaN 并置 NV;sat修饰把 -0 变 +0;pkcvt.unorm8*为 RNE;snorm 转换把 -1 编为 -32767。 fadd/pkadd等 H 格式 16 位运算只写rd所选半;移位量取低 4 位。
4.6 SFU 数值定义(A 档)
- 近似 SFU(exp2/log2/sin/cos/rsq)内部以 binary64 RNE 计算(vendored SoftFloat;多项式系数为 mpmath 200-bit 精确值的 RNE binary64),最后按目标 rm 舍入一次。
- 非 RNE 模式下结果是忠实舍入(真值两相邻可表示数之一,< 1 ulp),不保证方向正确;实测 RNE ≤ 0.5 ulp、其他 rm ≤ 1 ulp。
sin/cos输入单位是圈(sin(2*pi*x));rcp/sqrt/fsqrt/fdiv正确舍入;rsq为两步 RNE(rcp/rsq.f64恒 RNE,≥ 26 正确位);整数div/divu/rem/remu见 §4 开头。approx指令标志口径:数学结果 ≠ 所得位模式时置 NX(次正规或为零再加 UF);特殊操作数置 NV/DZ(rcp/rsq的 ±0 → DZ;log2(±0)→ DZ、负数/-inf → NV;rsq(负)→ NV;sin/cos(±inf)→ NV)。